﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Collections;
using System.IO;

namespace AndroidExploitationReverseShell
{
    /// <summary>
    /// listens for connections from SniffDroid clients
    /// accepts and handles new connections
    /// </summary>
    class NetworkService
    {
        //the thread that handles new connections
        private static Thread thread;
        //the list of active connections, thread-safe
        private static ArrayList connectionList = ArrayList.Synchronized(new ArrayList());

        /// <summary>
        /// starts the service and listens for connections
        /// </summary>
        public static void Start()
        {
            IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 80);
            Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
            sock.Bind(endPoint);
            sock.Listen(10);

            ParameterizedThreadStart startInfo = new ParameterizedThreadStart(AcceptConnections);
            thread = new Thread(startInfo);
            thread.Start(sock);
        }
        /// <summary>
        /// stops the service and stops listening
        /// </summary>
        public static void Stop()
        {
            thread.Abort();
        }
        /// <summary>
        /// removes a connection from the list of the currently active connections
        /// this method should be called by connections when the connection is lost
        /// </summary>
        /// <param name="connection">the connection to remove</param>
        public static void UnregisterConnection(Connection connection)
        {
            connectionList.Remove(connection);
        }
        /// <summary>
        /// add a new connection to the list of the currently active connections
        /// </summary>
        /// <param name="connection">the connection to add</param>
        private static void RegisterConnection(Connection connection)
        {
            connectionList.Add(connection);
            Session.GetSessionByIP(connection.IP).ResetExpirationCounter();
        }
        /// <summary>
        /// accepts the connection of the given socket
        /// </summary>
        /// <param name="sock">the socket to accept</param>
        private static void AcceptConnections(Object sock)
        {
            Socket socket = (Socket)sock;
            
            try 
            {
                while (true)
                {
                    //blocking call
                    Socket clientSocket = socket.Accept();
                    Connection session = new Connection(clientSocket);
                    RegisterConnection(session);
                }
            }
            catch
            {
                //prevent problems when sessions unregister themselves from the list during close
                ArrayList tmpList = (ArrayList)connectionList.Clone();
                foreach (Connection session in tmpList)
                {
                    session.Close();
                }
            }
        }


    }
}
